Passed
Push — master ( 040709...23067f )
by EMP
01:12
created

main.js ➔ addAddress   B

Complexity

Conditions 7

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 29
rs 7.952
c 0
b 0
f 0
cc 7
1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		document.getElementById("txt_skey").style.background = "#466";
8
		document.getElementById("txt_skey").maxLength = "64";
9
	} else {
10
		console.log("Failed to load All-Ears");
11
	}
12
});
13
14
function TabState(cur, max, btnDele, btnUpdt) {
15
	this.cur = cur;
16
	this.max = max;
17
	this.btnDele = btnDele;
18
	this.btnUpdt = btnUpdt;
19
}
20
21
const tabs = [
22
	new TabState(0, 0, false, true), // Inbox
23
	new TabState(0, 0, false, true), // Outbx
24
	new TabState(0, 2, true, false), // Write
25
	new TabState(0, 2, false, false), // Notes
26
	new TabState(0, 3, false, true) // Tools
27
];
28
29
let tab = 0;
30
const TAB_INBOX = 0;
31
const TAB_OUTBX = 1;
0 ignored issues
show
Unused Code introduced by
The constant TAB_OUTBX seems to be never used. Consider removing it.
Loading history...
32
const TAB_WRITE = 2;
33
const TAB_NOTES = 3;
34
const TAB_TOOLS = 4;
35
36
// Helper functions
37
function getCountryName(countryCode) {
38
	const opts = document.getElementById("gatekeeper_country");
39
40
	for (let i = 0; i < opts.length; i++) {
41
		if (opts[i].value === countryCode) {
42
			return opts[i].textContent;
43
		}
44
	}
45
46
	return "Unknown countrycode: " + countryCode;
47
}
48
49
function getCountryFlag(countryCode) {
50
	return sodium.to_string(new Uint8Array([
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
51
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
52
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
53
	]));
54
}
55
56
function getMsgId(num) {
57
	let i;
58
	if (ae.GetExtMsgHeaders(num).toLowerCase().slice(0, 11) === "message-id:") {
59
		i = 0;
60
	} else {
61
		i = ae.GetExtMsgHeaders(num).toLowerCase().indexOf("\nmessage-id:");
62
		if (i < 1) return "ERR";
63
		i++;
64
	}
65
66
	const x = ae.GetExtMsgHeaders(num).slice(i + 11).trim();
67
	if (x[0] !== "<") return "ERR2";
68
	return x.slice(1, x.indexOf(">"));
69
}
70
71
function displayFile(num) {
72
	document.getElementById("midright").scroll(0, 0);
73
	document.getElementById("btn_reply").disabled = true;
74
	document.getElementById("btn_mdele").disabled = true;
75
76
	document.getElementById("midright").children[0].hidden = true;
77
	document.getElementById("midright").children[1].textContent = ae.GetUplMsgTitle(num);
78
	document.getElementById("midright").children[2].textContent = ae.GetUplMsgBody(num);
79
}
80
81
function displayMsg(isInt, num) {
82
	document.getElementById("midright").scroll(0, 0);
83
84
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
85
86
	document.getElementById("btn_reply").disabled = false;
87
	document.getElementById("btn_reply").onclick = function() {
88
		document.getElementById("write_recv").value = isInt? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
89
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
90
		document.getElementById("write_rply").textContent = (isInt? "" : getMsgId(num));
91
		document.getElementById("btn_write").click();
92
		document.getElementById("div_write_1").hidden = false;
93
		document.getElementById("div_write_2").hidden = true;
94
		document.getElementById("write_body").focus();
95
		for (const opt of document.getElementById("write_from").options) {
96
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
97
				opt.selected = true;
98
			}
99
		}
100
	};
101
102
	document.getElementById("btn_mdele").disabled = false;
103
	document.getElementById("btn_mdele").onclick = function() {
104
		this.blur();
105
106
		ae.Message_Delete(isInt? ae.GetIntMsgIdHex(num) : ae.GetExtMsgIdHex(num), function(success) {
107
			if (!success) console.log("Failed delete");
108
		});
109
	};
110
111
	document.getElementById("midright").children[0].hidden = false;
112
	document.getElementById("midright").children[1].textContent = isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num);
113
	document.getElementById("midright").children[2].textContent = isInt ? ae.GetIntMsgBody(num) : ae.GetExtMsgBody(num);
114
115
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
116
	document.getElementById("readmsg_date").children[0].textContent = new Date(ts * 1000).toISOString().slice(0, 19).replace("T", " ");
117
118
	if (!isInt) {
119
		document.getElementById("readmsg_ip").hidden = false;
120
		document.getElementById("readmsg_country").hidden = false;
121
		document.getElementById("readmsg_tls").hidden = false;
122
		document.getElementById("readmsg_greet").hidden = false;
123
		document.getElementById("readmsg_timing").hidden = false;
124
		document.getElementById("readmsg_envfrom").hidden = false;
125
126
		const cc = ae.GetExtMsgCountry(num);
127
128
		document.getElementById("readmsg_ip").children[0].textContent = ae.GetExtMsgIp(num);
129
		document.getElementById("readmsg_country").textContent = getCountryFlag(cc) + " " + getCountryName(cc);
130
		document.getElementById("readmsg_tls").children[0].textContent = ae.GetExtMsgTLS(num);
131
		document.getElementById("readmsg_greet").children[0].textContent = ae.GetExtMsgGreet(num);
132
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
133
134
		let flagText = "";
135
		if (!ae.GetExtMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
136
		if (!ae.GetExtMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
137
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
138
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
139
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
140
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
141
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
142
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
143
	} else {
144
		document.getElementById("readmsg_ip").hidden = true;
145
		document.getElementById("readmsg_country").hidden = true;
146
		document.getElementById("readmsg_tls").hidden = true;
147
		document.getElementById("readmsg_greet").hidden = true;
148
		document.getElementById("readmsg_timing").hidden = true;
149
		document.getElementById("readmsg_envfrom").hidden = true;
150
151
		let symbol = "<span title=\"Invalid level\">&#x26a0;</span>";
152
		if (ae.GetIntMsgFrom(num) === "system") {if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"System\">&#x1f162;</span>";} // S (System)
153
		else if (ae.GetIntMsgLevel(num) === 0) symbol = "<span title=\"Level 0 User\">&#x1f10c;</span>"; // 0
154
		else if (ae.GetIntMsgLevel(num) === 1) symbol = "<span title=\"Level 1 User\">&#x278a;</span>"; // 1
155
		else if (ae.GetIntMsgLevel(num) === 2) symbol = "<span title=\"Level 2 User\">&#x278b;</span>"; // 2
156
		else if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"Administrator\">&#x1f150;</span>"; // A (Admin)
157
		document.getElementById("readmsg_from").innerHTML = symbol + " " + ae.GetIntMsgFrom(num);
158
159
		let flagText = "";
160
		if (!ae.GetIntMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
161
		if (!ae.GetIntMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
162
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
163
	}
164
}
165
166
// Interface
167
function addMsg(isInt, i) {
168
	const row = document.getElementById("tbl_inbox").insertRow(-1);
169
	const cellTime = row.insertCell(-1);
170
	const cellSubj = row.insertCell(-1);
171
	const cellSnd1 = row.insertCell(-1);
172
	const cellSnd2 = row.insertCell(-1);
173
174
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
175
	cellTime.setAttribute("data-ts", ts);
176
	cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 10);
177
178
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
179
180
	if (isInt) {
181
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
182
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : "";
183
	} else {
184
		const from1 = ae.GetExtMsgFrom(i);
185
		const from2 = from1.substring(from1.indexOf("@") + 1);
186
		const cc = ae.GetExtMsgCountry(i);
187
188
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
189
190
		const flag = document.createElement("abbr");
191
		flag.textContent = getCountryFlag(cc);
192
		flag.title = getCountryName(cc);
193
		cellSnd2.appendChild(flag);
194
195
		const fromText = document.createElement("span");
196
		fromText.textContent = " " + from2;
197
		cellSnd2.appendChild(fromText);
198
	}
199
200
	row.onclick = function() {
201
		displayMsg(isInt, i);
202
	};
203
}
204
205
function getRowsPerPage() {
206
	const tbl = document.getElementById("tbl_inbox");
207
	tbl.innerHTML = "";
208
	const row = tbl.insertRow(-1);
209
	const cell = row.insertCell(-1);
210
	cell.textContent = "0";
211
212
	const rowsPerPage = Math.floor(getComputedStyle(document.getElementById("div_inbox")).height.replace("px", "") / getComputedStyle(document.querySelector("#tbl_inbox > tbody > tr:first-child")).height.replace("px", "")) - 1; // -1 allows space for 'load more'
213
	tbl.innerHTML = "";
214
	return rowsPerPage;
215
}
216
217
function addMessages() {
218
	const rowsPerPage = getRowsPerPage();
219
	let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
220
221
	const maxExt = ae.GetExtMsgCount();
222
	const maxInt = ae.GetIntMsgCount();
223
224
	tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt) / rowsPerPage);
225
226
	let numExt = 0;
227
	let numInt = 0;
228
	let numAdd = 0;
229
230
	while (numAdd < rowsPerPage) {
231
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : -1;
232
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : -1;
233
		if (tsInt === -1 && tsExt === -1) break;
234
235
		if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
236
			if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
237
			numInt++;
238
		} else if (tsExt !== -1) {
239
			if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
240
			numExt++;
241
		}
242
	}
243
244
	if (ae.GetReadyMsgKilos() < ae.GetTotalMsgKilos()) {
245
		const inbox = document.getElementById("tbl_inbox");
246
		const row = inbox.insertRow(-1);
247
		const cell = row.insertCell(-1);
248
		cell.textContent = "Load more (" + (ae.GetTotalMsgKilos() - ae.GetReadyMsgKilos()) + " KiB left)";
249
250
		row.onclick = function() {
251
			this.onclick = "";
252
253
			ae.Message_Browse(false, function(successBrowse) {
254
				document.getElementById("tbl_inbox").style.opacity = 1;
255
256
				if (successBrowse) {
257
					addMessages();
258
					if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
259
				}
260
			});
261
		};
262
	}
263
}
264
265
function addUploads() {
266
	const tbl = document.getElementById("tbd_uploads");
267
	tbl.innerHTML = "";
268
269
	for (let i = 0; i < ae.GetUplMsgCount(); i++) {
270
		const row = tbl.insertRow(-1);
271
		let cell;
272
		cell = row.insertCell(-1); cell.textContent = new Date(ae.GetUplMsgTime(i) * 1000).toISOString().slice(0, 10);
273
274
		cell = row.insertCell(-1); cell.textContent = ae.GetUplMsgTitle(i);
275
		cell.onclick = function() {displayFile(this.parentElement.rowIndex - 1);};
276
277
		cell = row.insertCell(-1); cell.textContent = ""; // Format
278
		cell = row.insertCell(-1); cell.textContent = ""; // Size
279
280
		cell = row.insertCell(-1); cell.innerHTML = "<button data-msgid=\"" + ae.GetUplMsgIdHex(i) + "\" type=\"button\">X</button>";
281
		cell.children[0].onclick = function() {
282
			const tr = this.parentElement.parentElement;
283
			ae.Message_Delete(this.getAttribute("data-msgid"), function(success) {
284
				if (success) tr.remove();
285
			});
286
		};
287
	}
288
}
289
290
function updateAddressCounts() {
291
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetAddressLimitNormal(ae.GetUserLevel())).padStart(ae.GetAddressLimitNormal(ae.GetUserLevel()) > 9 ? 5 : 1);
292
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetAddressLimitShield(ae.GetUserLevel())).padStart(ae.GetAddressLimitShield(ae.GetUserLevel()) > 9 ? 5 : 1);
293
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
294
}
295
296
function adjustLevel(pubkey, level, c) {
297
	const fs = document.getElementById("fs_accs");
298
	fs.disabled = true;
299
300
	ae.Account_Update(pubkey, level, function(success) {
301
		fs.disabled = false;
302
303
		if (success) {
304
			c[4].textContent = level;
305
			c[5].children[0].disabled = (level === 3);
306
			c[6].children[0].disabled = (level === 0);
307
		}
308
	});
309
}
310
311
function addAccountToTable(i) {
312
	const tblAccs = document.getElementById("tbd_accs");
313
	const row = tblAccs.insertRow(-1);
314
	let cell;
315
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserPkHex(i);
316
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSpace(i);
317
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserNAddr(i);
318
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSAddr(i);
319
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserLevel(i);
320
321
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">+</button>";
322
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) + 1, c);};
323
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 3);
324
325
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">&minus;</button>";
326
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) - 1, c);};
327
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 0);
328
329
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">X</button>";
330
	cell.children[0].onclick = function() {
331
		const tr = this.parentElement.parentElement;
332
		ae.Account_Delete(tr.cells[0].textContent, function(success) {
333
			if (success) tr.remove();
334
		});
335
	};
336
}
337
338
function reloadAccount() {
339
	// Limits
340
	const tblLimits = document.getElementById("tbl_limits");
341
	for (let i = 0; i < 4; i++) {
342
		tblLimits.rows[i].cells[1].children[0].value = ae.GetStorageLimit(i) + 1;
343
		tblLimits.rows[i].cells[2].children[0].value = ae.GetAddressLimitNormal(i);
344
		tblLimits.rows[i].cells[3].children[0].value = ae.GetAddressLimitShield(i);
345
	}
346
347
	// Accounts
348
	const tblAccs = document.getElementById("tbd_accs");
349
350
	// All: Our account
351
	const row = tblAccs.insertRow(-1);
352
	let cell;
353
	cell = row.insertCell(-1); cell.textContent = ae.GetUserPkHex();
354
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.GetTotalMsgKilos() / 1024);
355
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountNormal();
356
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountShield();
357
	cell = row.insertCell(-1); cell.textContent = ae.GetUserLevel();
358
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\" disabled=\"disabled\">+</button>";
359
360
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_downme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">&minus;</button>";
361
	cell.children[0].onclick = function() {
362
		const newLevel = parseInt(row.cells[4].textContent) - 1;
363
		ae.Account_Update(ae.GetUserPkHex(), newLevel, function(success) {
364
			if (success) row.cells[4].textContent = newLevel;
365
		});
366
	};
367
368
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_killme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">X</button>";
369
	cell.children[0].onclick = function() {
370
		ae.Account_Delete(ae.GetUserPkHex(), function(success) {
371
			if (success) row.remove();
372
		});
373
	};
374
375
	// Admin: Other accounts
376
	if (ae.IsUserAdmin()) {
377
		for (let i = 0; i < ae.Admin_GetUserCount(); i++) {
378
			addAccountToTable(i);
379
		}
380
	}
381
382
	document.getElementById("txt_reg").disabled = !ae.IsUserAdmin();
383
	document.getElementById("btn_reg").disabled = !ae.IsUserAdmin();
384
385
	// Contacts
386
	for (let i = 0; i < ae.GetContactCount(); i++) {
387
		addContact(
388
			ae.GetContactMail(i),
389
			ae.GetContactName(i),
390
			ae.GetContactNote(i)
391
		);
392
	}
393
394
	// Addresses
395
	for (let i = 0; i < ae.GetAddressCount(); i++) {
396
		addAddress(i);
397
	}
398
399
	updateAddressCounts();
400
}
401
402 View Code Duplication
function deleteAddress(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
403
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
404
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
405
406
	let addressToDelete = -1;
407
408
	for (let i = 0; i < ae.GetAddressCount(); i++) {
409
		if (addr === ae.GetAddress(i)) {
410
			addressToDelete = i;
411
			break;
412
		}
413
	}
414
415
	if (addressToDelete === -1) return;
416
417
	ae.Address_Delete(addressToDelete, function(success) {
418
		if (success) {
419
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
420
			document.getElementById("write_from").remove(addressToDelete);
421
			updateAddressCounts();
422
423
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
424
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
425
426
			ae.Private_Update(function(success2) {
427
				if (!success2) console.log("Failed to update the Private field");
428
429
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
430
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
431
			});
432
		} else {
433
			console.log("Failed to delete address");
434
435
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
436
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
437
		}
438
	});
439
}
440
441 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
442
	let newAddr = "";
443
444
	for (let i = 0; i < 16; i++) {
445
		switch (addr.charAt(i)) {
446
			case '1':
447
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
448
				break;
449
			case '0':
450
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
451
				break;
452
			case 'w':
453
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
454
				break;
455
			default:
456
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
457
		}
458
	}
459
460
	return newAddr;
461
}
462
463
function addAddress(num) {
464
	const addrTable = document.getElementById("tbl_addrs");
465
	const row = addrTable.insertRow(-1);
466
	const cellAddr = row.insertCell(-1);
467
	const cellChk1 = row.insertCell(-1);
468
	const cellChk2 = row.insertCell(-1);
469
	const cellChk3 = row.insertCell(-1);
470
	const cellBtnD = row.insertCell(-1);
471
472
	cellAddr.textContent = ae.GetAddress(num);
473
	cellAddr.onclick = function() {
474
		if (cellAddr.textContent.length === 16)
475
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomainEml());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
476
		else
477
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomainEml());
478
	};
479
480
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
481
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
482
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
483
484
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
485
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
486
487
	const opt = document.createElement("option");
488
	opt.value = cellAddr.textContent;
489
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomainEml();
490
	document.getElementById("write_from").appendChild(opt);
491
}
492
493
document.getElementById("btn_dele").onclick = function() {
494
	this.blur();
495
496
	if (tab === TAB_WRITE) {
497
		tabs[tab].cur = 0;
498
		updateTab();
499
500
		document.getElementById("write_recv").value = "";
501
		document.getElementById("write_subj").value = "";
502
		document.getElementById("write_body").value = "";
503
504
		document.getElementById("write_recv").focus();
505
	}
506
};
507
508
document.getElementById("btn_updt").onclick = function() {
509
	const btn = this;
510
	btn.disabled = true;
511
	btn.blur();
512
513
	if (tab === TAB_INBOX) {
514
		document.getElementById("tbl_inbox").style.opacity = 0.5;
515
516
		ae.Message_Browse(true, function(successBrowse) {
517
			document.getElementById("tbl_inbox").style.opacity = 1;
518
519
			if (successBrowse) {
520
				addMessages();
521
				addUploads();
522
				btn.disabled = false;
523
			} else {
524
				console.log("Failed to refresh");
525
				btn.disabled = false;
526
			}
527
		});
528
	}
529
};
530
531
function addContact(mail, name, note) {
532
	const tbl = document.getElementById("tbl_ctact");
533
	const row = tbl.insertRow(-1);
534
	const cellMail = row.insertCell(-1);
535
	const cellName = row.insertCell(-1);
536
	const cellNote = row.insertCell(-1);
537
	const cellBtnD = row.insertCell(-1);
538
539
	cellMail.textContent = mail;
540
	cellName.textContent = name;
541
	cellNote.textContent = note;
542
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
543
544
	cellMail.contentEditable = true;
545
	cellName.contentEditable = true;
546
	cellNote.contentEditable = true;
547
548
	cellBtnD.onclick = function() {row.remove();};
549
}
550
551
document.getElementById("btn_newcontact").onclick = function() {
552
	addContact("", "", "");
553
};
554
555
document.getElementById("btn_savecontacts").onclick = function() {
556
	while (ae.GetContactCount() > 0) {
557
		ae.DeleteContact(0);
558
	}
559
560
	for (const row of document.getElementById("tbl_ctact").rows) {
561
		ae.AddContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
562
	}
563
564
	const btn = this;
565
	btn.disabled = true;
566
567
	ae.Private_Update(function(success) {
568
		btn.disabled = false;
569
570
		if (!success) {
571
			console.log("Failed contacts update");
572
		}
573
	});
574
};
575
576
function updateTab() {
577
	switch (tab) {
578
		case TAB_INBOX:
579
			addMessages();
580
		break;
581
582
		case TAB_WRITE:
583
			switch (tabs[tab].cur) {
584
				case 0: // Write
585
					document.getElementById("div_write_1").hidden = false;
586
					document.getElementById("div_write_2").hidden = true;
587
					document.getElementById("write_body").focus();
588
				break;
589
590
				case 1: // Verify
591
					ae.Address_Lookup(document.getElementById("write_recv").value, function(pk) {
592
						if (pk) {
593
							document.getElementById("div_write_1").hidden = true;
594
							document.getElementById("div_write_2").hidden = false;
595
596
							document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.GetDomainEml();
597
							document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
598
							document.getElementById("write2_pkey").textContent = sodium.to_hex(pk);
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
599
600
							document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
601
							document.getElementById("write2_rply").textContent = document.getElementById("write_rply").textContent;
602
							document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
603
						} else {
604
							console.log("Failed lookup");
605
						}
606
					});
607
				break;
608
609
				case 2: // Send
610
					ae.Message_Create(
611
						document.getElementById("write_subj").value,
612
						document.getElementById("write_body").value,
613
						document.getElementById("write_from").value,
614
						document.getElementById("write_recv").value,
615
						document.getElementById("write_rply").textContent,
616
						(document.getElementById("write2_recv").textContent.indexOf("@") > 0) ? null : sodium.from_hex(document.getElementById("write2_pkey").textContent),
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
617
						function(success) {
618
							if (success) {
619
								console.log("Sent ok");
620
							} else {
621
								console.log("Failed sending");
622
							}
623
						}
624
					);
625
				break;
626
			}
627
		break;
628
629
		case TAB_NOTES:
630
			for (let i = 0; i <= tabs[tab].max; i++) {
631
				document.getElementById("div_notes").children[i].hidden = (i !== tabs[tab].cur);
632
			}
633
		break;
634
635
		case TAB_TOOLS:
636
			for (let i = 0; i <= tabs[tab].max; i++) {
637
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
638
			}
639
		break;
640
	}
641
642
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
643
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
644
}
645
646
document.getElementById("btn_left").onclick = function() {
647
	tabs[tab].cur--;
648
	if (tabs[tab].cur === 0) this.disabled = true;
649
	if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
650
	updateTab();
651
	this.blur();
652
};
653
654
document.getElementById("btn_rght").onclick = function() {
655
	tabs[tab].cur++;
656
	if (tabs[tab].cur === tabs[tab].max) this.disabled = true;
657
	document.getElementById("btn_left").disabled = false;
658
	updateTab();
659
	this.blur();
660
};
661
662
const buttons = document.querySelector("#main1 > .top").getElementsByTagName("button");
663
for (let i = 0; i < buttons.length; i++) {
664
	buttons[i].onclick = function() {
665
		tab = i;
666
667
		for (let j = 0; j < buttons.length; j++) {
668
			document.querySelector("#main1 > .mid").children[j].hidden = (tab !== j);
669
			buttons[j].disabled = (tab === j);
670
		}
671
672
		document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
0 ignored issues
show
Bug introduced by
The variable tab is changed as part of the for loop for example by i on line 665. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
673
		document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
674
		document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
675
		document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
676
	};
677
}
678
679
function addressCreate(addr) {
680
	const btnN = document.getElementById("btn_address_create_normal");
681
	const btnS = document.getElementById("btn_address_create_shield");
682
	btnN.disabled = true;
683
	btnS.disabled = true;
684
685
	ae.Address_Create(addr, function(success1) {
686
		if (success1) {
687
			ae.Private_Update(function(success2) {
688
				addAddress(ae.GetAddressCount() - 1);
689
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
690
				updateAddressCounts();
691
692
				if (!success2) console.log("Failed to update the Private field");
693
694
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
695
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
696
			});
697
		} else {
698
			console.log("Failed to add address");
699
700
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
701
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
702
		}
703
	});
704
}
705
706
document.getElementById("btn_address_create_normal").onclick = function() {
707
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
708
709
	const txtNewAddr = document.getElementById("txt_address_create_normal");
710
	if (!txtNewAddr.reportValidity()) return;
711
712
	addressCreate(txtNewAddr.value);
713
};
714
715
document.getElementById("btn_address_create_shield").onclick = function() {
716
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
717
718
	addressCreate("SHIELD");
719
};
720
721
document.getElementById("btn_reg").onclick = function() {
722
	const btn = document.getElementById("btn_reg");
723
	const txt = document.getElementById("txt_reg");
724
	if (!txt.reportValidity()) return;
725
	btn.disabled = true;
726
727
	ae.Account_Create(txt.value, function(success) {
728
		if (success) {
729
			addAccountToTable(ae.Admin_GetUserCount() - 1);
730
			txt.value = "";
731
		}
732
733
		btn.disabled = false;
734
	});
735
};
736
737
document.getElementById("chk_downme").onclick = function() {document.getElementById("btn_downme").disabled = !this.checked;};
738
document.getElementById("chk_killme").onclick = function() {document.getElementById("btn_killme").disabled = !this.checked;};
739
740
document.getElementById("btn_notepad_saveupl").onclick = function() {
741
	const np = document.getElementById("txt_notepad");
742
	np.disabled = true;
743
744
	let fname = prompt("Save as...", "Untitled");
0 ignored issues
show
Debugging Code Best Practice introduced by
The prompt UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
745
	if (!fname.endsWith(".txt")) fname += ".txt";
746
747
	ae.Message_Upload(fname, np.value, false, function(success) {
748
		if (success) {
749
			np.value = "";
750
			addUploads();
751
		}
752
753
		console.log("Failed to add text");
754
		np.disabled = false;
755
	});
756
};
757
758
document.getElementById("txt_skey").onkeyup = function(event) {
759
	if (event.key === "Enter") {
760
		event.preventDefault();
761
		document.getElementById("btn_enter").click();
762
	}
763
};
764
765
document.getElementById("btn_enter").onclick = function() {
766
	const txtSkey = document.getElementById("txt_skey");
767
	if (!txtSkey.reportValidity()) return;
768
769
	const btn = this;
770
	btn.disabled = true;
771
	document.getElementById("txt_skey").style.background = "#233";
772
773
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
774
		if (successSetKeys) {
775
			ae.Account_Browse(0, function(successBrowse) {
776
				if (successBrowse) {
777
					txtSkey.value = "";
778
779
					reloadAccount();
780
					document.getElementById("div_begin").hidden = true;
781
					document.getElementById("div_main").style.display = "grid";
782
783
					document.getElementById("btn_updt").click();
784
				} else {
785
					console.log("Failed to enter");
786
					btn.disabled = false;
787
					document.getElementById("txt_skey").style.background = "#466";
788
					txtSkey.focus();
789
				}
790
			});
791
		} else {
792
			console.log("Invalid format for key");
793
			btn.disabled = false;
794
			document.getElementById("txt_skey").style.background = "#466";
795
			txtSkey.focus();
796
		}
797
	});
798
};
799
800
});
801